package com.hung.trade.order.services.impl;

import com.alibaba.fastjson.JSON;
import com.hung.trade.common.api.ICouponApi;
import com.hung.trade.common.api.IGoodsApi;
import com.hung.trade.common.api.IUserApi;
import com.hung.trade.common.constants.TradeEnums;
import com.hung.trade.common.exception.OrderException;
import com.hung.trade.common.exception.TradeException;
import com.hung.trade.common.protocol.OrderCancelMessage;
import com.hung.trade.common.protocol.coupon.ChangeCouponReq;
import com.hung.trade.common.protocol.coupon.ChangeCouponResp;
import com.hung.trade.common.protocol.coupon.QueryCouponReq;
import com.hung.trade.common.protocol.coupon.QueryCouponResp;
import com.hung.trade.common.protocol.goods.QueryGoodsReq;
import com.hung.trade.common.protocol.goods.QueryGoodsResp;
import com.hung.trade.common.protocol.goods.ReduceGoodsNumberReq;
import com.hung.trade.common.protocol.goods.ReduceGoodsNumberResp;
import com.hung.trade.common.protocol.order.ConfirmOrderReq;
import com.hung.trade.common.protocol.order.ConfirmOrderResp;
import com.hung.trade.common.protocol.pay.ChangeUserMoneyReq;
import com.hung.trade.common.protocol.pay.ChangeUserMoneyResp;
import com.hung.trade.common.protocol.user.QueryUserReq;
import com.hung.trade.common.protocol.user.QueryUserResp;
import com.hung.trade.common.rocketmq.RocketMQProducer;
import com.hung.trade.common.utils.IdGenerator;
import com.hung.trade.dao.mapper.TradeOrderMapper;
import com.hung.trade.dao.pojo.TradeOrder;
import com.hung.trade.dao.pojo.TradeOrderExample;
import com.hung.trade.order.services.IOrderService;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.producer.SendResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;

/**
 * @author hungki
 * @createTime 2018-10-09 上午 1:58
 */
@Service
public class OrderServiceImpl implements IOrderService {
    @Autowired
    private TradeOrderMapper tradeOrderMapper;
    @Autowired
    private IGoodsApi iGoodsApi;
    @Autowired
    private ICouponApi iCouponApi;
    @Autowired
    private IUserApi iUserApi;
    @Autowired
    RocketMQProducer rocketMQProducer;
    @Override
    @Transactional
    public ConfirmOrderResp confirmOrder(ConfirmOrderReq confirmOrderReq) {

        ConfirmOrderResp confirmOrderResp = new ConfirmOrderResp();

        QueryGoodsReq queryGoodsReq = new QueryGoodsReq();
        queryGoodsReq.setGoodsId(confirmOrderReq.getGoodsId());
        QueryGoodsResp queryGoodsResp = iGoodsApi.queryGoodsById(queryGoodsReq);
        checkQueryGoodsResp(confirmOrderReq,queryGoodsResp);
        //1、检查校验
        checkConfirmOrderReq(confirmOrderReq);
        //2、创建不可见订单
        TradeOrder tradeOrder =saveNoConfirmOrder(confirmOrderReq);
        //3、调用远程服务，扣除优惠券，库存，余额，如果调用成功，更改订单状态为可见，
        // 如果其中某一个服务失败，发送mq消息取消订单

        try {
            callRemoteService(tradeOrder.getOrderId(), confirmOrderReq);
        }catch (Exception e){
            e.printStackTrace();
            confirmOrderResp.setRetCode(TradeEnums.RetEnum.FAIL.getCode());
            confirmOrderResp.setRetInfo(TradeEnums.RetEnum.FAIL.getDesc()+":"+e.getMessage());
            //调用远程方法，不抛出异常，这样本方法体内的事务可以提交，创建临时不可见数据，发mq异步取消临时数据
            //throw new OrderException(e);
        }
        //4、
        return confirmOrderResp;
    }

    private void callRemoteService(String orderId,ConfirmOrderReq confirmOrderReq) {
        try{

            //调用优惠券
            if(StringUtils.isNotBlank(confirmOrderReq.getCouponId())){
                ChangeCouponReq changeCouponReq =new ChangeCouponReq();
                changeCouponReq.setUserId(confirmOrderReq.getUserId());
                changeCouponReq.setCouponId(confirmOrderReq.getCouponId());
                changeCouponReq.setOrderId(orderId);
                changeCouponReq.setIsUsed(TradeEnums.YesNoEnum.YES.getCode());
                ChangeCouponResp changeCouponResp = iCouponApi.changeCoupon(changeCouponReq);
                System.out.println("changeCouponResp = " + changeCouponResp);
                if(null==changeCouponResp || !TradeEnums.RetEnum.SUCCESS.getCode().equals(changeCouponResp.getRetCode())){
                    throw new OrderException(changeCouponResp.getRetInfo());
                }
            }

            //扣余额
            if(null!=confirmOrderReq.getMoneyPaid() && confirmOrderReq.getMoneyPaid().compareTo(BigDecimal.ZERO)>0){
                ChangeUserMoneyReq changeUserMoneyReq =new ChangeUserMoneyReq();
                changeUserMoneyReq.setOrderId(orderId);
                changeUserMoneyReq.setUserId(confirmOrderReq.getUserId());
                changeUserMoneyReq.setUserMoney(confirmOrderReq.getMoneyPaid());
                changeUserMoneyReq.setMoneyLogType(TradeEnums.UserMoneyLogTypeEnum.PAID.getCode());

                ChangeUserMoneyResp changeUserMoneyResp =iUserApi.changeUserMoney(changeUserMoneyReq);
                if(null==changeUserMoneyResp || !TradeEnums.RetEnum.SUCCESS.getCode().equals(changeUserMoneyResp.getRetCode())){
                    throw new OrderException("扣除余额失败");
                }
            }


            //扣库存
            ReduceGoodsNumberReq reduceGoodsNumberReq = new ReduceGoodsNumberReq();
            reduceGoodsNumberReq.setOrderId(orderId);
            reduceGoodsNumberReq.setGoodsId(confirmOrderReq.getGoodsId());
            reduceGoodsNumberReq.setGoodsNumber(confirmOrderReq.getGoodsNumber());

            ReduceGoodsNumberResp reduceGoodsNumberResp = iGoodsApi.reduceGoodsNumberById(reduceGoodsNumberReq);
            if(null==reduceGoodsNumberResp || !TradeEnums.RetEnum.SUCCESS.getCode().equals(reduceGoodsNumberResp.getRetCode())){
                throw new OrderException("扣除库存失败");
            }
            //修改订单状态
            TradeOrder tradeOrder = new TradeOrder();
            tradeOrder.setOrderId(orderId);
            tradeOrder.setOrderStatus(TradeEnums.OrderStatusEnum.CONFIRM.getStatusCode());
            tradeOrder.setConfirmTime(new Date());

            TradeOrderExample example = new TradeOrderExample() ;
            example.createCriteria().andOrderIdEqualTo(tradeOrder.getOrderId());
             int i = tradeOrderMapper.updateByExampleSelective(tradeOrder,example);
            if(i<=0){
                throw new OrderException("更新订单为可见订单失败");
            }
        }catch (Exception e){

            e.printStackTrace();
            //TODO 发送mq
            OrderCancelMessage orderCancelMessage = new OrderCancelMessage();
            orderCancelMessage.setUserId(confirmOrderReq.getUserId());
            orderCancelMessage.setGoodsNumber(confirmOrderReq.getGoodsNumber());
            orderCancelMessage.setOrderId(orderId);
            orderCancelMessage.setCouponId(confirmOrderReq.getCouponId());
            orderCancelMessage.setGoodsId(confirmOrderReq.getGoodsId());
            orderCancelMessage.setUserMoney(confirmOrderReq.getMoneyPaid());

            try {
                SendResult sentResult =rocketMQProducer.sendMsg(TradeEnums.OrderTopicAndTagEnum.ORDER_CANCEL,confirmOrderReq.getOrderId(), JSON.toJSONString(orderCancelMessage));
                System.out.println("sentResult = " + sentResult);
            } catch (TradeException e1) {
                throw new OrderException(e1);
            }
            throw  new OrderException(e);
        }
    }

    private TradeOrder saveNoConfirmOrder(ConfirmOrderReq confirmOrderReq) {

        TradeOrder tradeOrder = new TradeOrder();
        tradeOrder.setOrderId(IdGenerator.generatorUUID());
        tradeOrder.setUserId(confirmOrderReq.getUserId());
        tradeOrder.setAddress(confirmOrderReq.getAddress());
        tradeOrder.setConsignee(confirmOrderReq.getConsignee());
        tradeOrder.setGoodsId(confirmOrderReq.getGoodsId());
        tradeOrder.setGoodsPrice(confirmOrderReq.getGoodsPrice());

        tradeOrder.setOrderStatus(TradeEnums.OrderStatusEnum.NO_CONFIRM.getStatusCode());
        tradeOrder.setPayStatus(TradeEnums.PayStatusEnum.NO_PAY.getStatusCode());
        tradeOrder.setShippingStatus(TradeEnums.ShippingStatusEnum.NO_SHIP.getStatusCode());
        BigDecimal goodsAmount = confirmOrderReq.getGoodsPrice().multiply(new BigDecimal(confirmOrderReq.getGoodsNumber()));
        tradeOrder.setGoodsAmount(goodsAmount);
        BigDecimal shippingFee = calculateShippingFee(goodsAmount);
        tradeOrder.setShippingFee(shippingFee);
        if(shippingFee.compareTo(confirmOrderReq.getShippingFee()==null?new BigDecimal(0):confirmOrderReq.getShippingFee())!=0){
            throw new OrderException("快递费用不正确");
        }
        BigDecimal orderAmount = goodsAmount.add(shippingFee);
        if(orderAmount.compareTo(confirmOrderReq.getOrderAmount())!=0){
            throw new OrderException("订单金额异常");
        }

        Long couponId = confirmOrderReq.getGoodsId();
        if(null!=couponId){
            QueryCouponReq queryCouponReq = new QueryCouponReq();
            queryCouponReq.setUserId(confirmOrderReq.getUserId());
            queryCouponReq.setCouponId(confirmOrderReq.getCouponId());

            QueryCouponResp queryCouponResp =iCouponApi.queryCoupon(queryCouponReq);
            if(null==queryCouponResp || !TradeEnums.RetEnum.SUCCESS.getCode().equals(queryCouponResp.getRetCode())){
                throw new OrderException("优惠券非法");
            }

            if(TradeEnums.YesNoEnum.YES.getCode().equals(queryCouponResp.getIsUsed())){
                throw new OrderException("优惠券已使用");
            }
            tradeOrder.setCouponId(confirmOrderReq.getCouponId());
            tradeOrder.setCouponPaid(queryCouponResp.getCouponPrice());

        }else{
            tradeOrder.setCouponPaid(BigDecimal.ZERO);
        }
        //余额支付
        if(null!=confirmOrderReq.getMoneyPaid()){
            QueryUserReq queryUserReq = new QueryUserReq();
            queryUserReq.setUserId(confirmOrderReq.getUserId());

            QueryUserResp queryUserResp =iUserApi.queryUserById(queryUserReq);
            if(null==queryUserResp || !queryUserResp.getRetCode().equals(TradeEnums.RetEnum.SUCCESS.getCode())){
                throw new OrderException("用户非法");
            }
            if(queryUserResp.getUserMoney().compareTo(BigDecimal.ZERO)<=0){
                throw new OrderException("余额不足");
            }
            tradeOrder.setMoneyPaid(confirmOrderReq.getMoneyPaid());
        }else{
            tradeOrder.setMoneyPaid(BigDecimal.ZERO);
        }

        BigDecimal payAmount = orderAmount.subtract(tradeOrder.getCouponPaid()).subtract(tradeOrder.getMoneyPaid());
        tradeOrder.setPayAmount(payAmount);
        tradeOrder.setAddTime(new Date());

        System.out.println("tradeOrder = " + tradeOrder);
        int inesrt = tradeOrderMapper.insert(tradeOrder);
        if(inesrt<=0){
            throw  new OrderException("创建用户不可见订单异常");
        }
        return tradeOrder;

    }

    private BigDecimal calculateShippingFee(BigDecimal goodsAmount) {
        if(goodsAmount.compareTo(new BigDecimal(100))>0){
            return new BigDecimal(0);
        }else{
            return new BigDecimal(10);
        }
    }


    private void checkQueryGoodsResp(ConfirmOrderReq confirmOrderReq ,QueryGoodsResp queryGoodsResp) {

        if(null==queryGoodsResp || !queryGoodsResp.getRetCode().equals(TradeEnums.RetEnum.SUCCESS.getCode())|| queryGoodsResp.getGoodsId()==null){
            throw new OrderException("没有找到商品");
        }
        if(confirmOrderReq.getGoodsNumber()>queryGoodsResp.getGoodsNumber()){
            throw new OrderException("库存不足");
        }
        if(confirmOrderReq.getGoodsPrice().equals(queryGoodsResp.getGoodsPrice())){
            throw new OrderException("商品价格已变更，请重新下单");
        }

    }

    private void checkConfirmOrderReq(ConfirmOrderReq confirmOrderReq) {
        if(null==confirmOrderReq){
            throw new OrderException("下单信息不能为空");
        }
        if(null==confirmOrderReq.getUserId()){
            throw new OrderException("用户id不能为空");
        }
        if(null==confirmOrderReq.getGoodsId()){
            throw new OrderException("商品id不能为空");
        }
    }
}
